﻿
Imports osi.root.delegates
Imports osi.root.formation
Imports osi.root.procedure
Imports osi.root.utils

Public Module _allocator
    Public Function make_allocator(Of T, PARA_T)(ByVal i As Func(Of pointer(Of T), PARA_T, event_comb)) _
                                                As allocator(Of T, PARA_T)
        Return New allocator(Of T, PARA_T)(i)
    End Function

    Public Function make_allocator(Of T, PARA_T)(ByVal i As Func(Of PARA_T, pointer(Of T), event_comb)) _
                                                As allocator(Of T, PARA_T)
        Return New allocator(Of T, PARA_T)(i)
    End Function

    Public Function make_allocator(Of T, PARA_T)(ByVal i As Func(Of PARA_T, T)) _
                                                As allocator(Of T, PARA_T)
        Return New allocator(Of T, PARA_T)(i)
    End Function

    Public Function make_allocator(Of T, PARA_T)(ByVal i As _do_val_ref(Of PARA_T, T, Boolean)) _
                                                As allocator(Of T, PARA_T)
        Return New allocator(Of T, PARA_T)(i)
    End Function
End Module

Public Class allocator(Of T, PARA_T)
    Private ReadOnly alloc As Func(Of pointer(Of T), PARA_T, event_comb)

    Public Sub New(ByVal alloc As Func(Of pointer(Of T), PARA_T, event_comb))
        assert(Not alloc Is Nothing)
        Me.alloc = alloc
    End Sub

    Public Sub New(ByVal alloc As Func(Of PARA_T, pointer(Of T), event_comb))
        Me.New(Function(i As pointer(Of T), p As PARA_T) As event_comb
                   assert(Not alloc Is Nothing)
                   Return alloc(p, i)
               End Function)
    End Sub

    Public Sub New(ByVal alloc As Func(Of PARA_T, T))
        Me.New(Function(i As pointer(Of T), p As PARA_T) As event_comb
                   assert(Not alloc Is Nothing)
                   Return New event_comb(Function() As Boolean
                                             Dim o As T = Nothing
                                             o = alloc(p)
                                             Return eva(i, o) AndAlso
                                                    goto_end()
                                         End Function)
               End Function)
    End Sub

    Public Sub New(ByVal alloc As _do_val_ref(Of PARA_T, T, Boolean))
        Me.New(Function(i As pointer(Of T), p As PARA_T) As event_comb
                   assert(Not alloc Is Nothing)
                   Return New event_comb(Function() As Boolean
                                             Dim o As T = Nothing
                                             If alloc(p, o) Then
                                                 Return eva(i, o) AndAlso
                                                        goto_end()
                                             Else
                                                 Return False
                                             End If
                                         End Function)
               End Function)
    End Sub

    Default Public ReadOnly Property allocate(ByVal i As pointer(Of T), ByVal p As PARA_T) As event_comb
        Get
            Return alloc(i, p)
        End Get
    End Property
End Class
